package com.lh0811.forge.dependency.security.client.component.annotation;

import com.lh0811.forge.dependency.basic_web.exception.CommonException;
import com.lh0811.forge.dependency.basic_web.response.ServerResponse;
import com.lh0811.forge.dependency.security.client.service.SecurityClient;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.lang.annotation.Annotation;

/**
 * @author lh0811
 * @date 2021/5/10
 */
@Aspect
@Slf4j
@Component
public class HasUrlAop extends AuthAbstractClass {

    @Resource
    private SecurityClient securityClient;

    @Pointcut("@within(com.lh0811.forge.dependency.security.client.component.annotation.HasUrl) || @annotation(com.lh0811.forge.dependency.security.client.component.annotation.HasUrl)")
    public void annotationPointCut() {
    }


    @Around("annotationPointCut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        log.debug("进入HasUrlAop切面");
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        // 获取方法上的HasUrl注解
        HasUrl annotation = signature.getMethod().getAnnotation(HasUrl.class);
        // 方法上不存在
        if (annotation == null) {
            // 获取类上的HasUrl
            Annotation declaredAnnotation = signature.getDeclaringType().getDeclaredAnnotation(HasUrl.class);
            if (declaredAnnotation != null) {
                annotation = (HasUrl) declaredAnnotation;
            }
        }

        // 获取请求的URL
        String url = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest().getRequestURI();
        if (StringUtils.isBlank(url)) {
            throw CommonException.create(ServerResponse.createByError("使用HasUrl标志的方法必须在请求上下文中:" + signature.getDeclaringType().getName() + "." + signature.getMethod().getName()));
        }
        // 判断URL是否在授权范围内
        securityClient.hasUrl(url);
        // 鉴权通过后，执行原函数
        Object proceed = joinPoint.proceed(joinPoint.getArgs());
        log.debug("退出HasUrlAop切面");
        return proceed;
    }

}
